package seedpod.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import seedpod.exceptions.SeedpodException;
import seedpod.kb2db.ClsMap;
import seedpod.kb2db.SlotMap;
import seedpod.rdb.PMFactory;

public abstract class Relationship {
	public static SlotMap getFromSlot( ClsMap reifiedCls ) {
		Collection<SlotMap> slots = reifiedCls.getSlotMaps();
		Iterator<SlotMap> slotItr = slots.iterator();
		SlotMap slot;
		while (slotItr.hasNext()) {
			slot = slotItr.next();
			if ( slot.getName().startsWith( "FROM" ) ) return slot;
		}
		return null;
	}

	public static String getInverseSlotName( SlotMap slot ) {
		return slot.getSlotInverse();
	}

	public static String getTargetClassName( SlotMap attribute ) {
		return attribute.getRdbTargetName();
	}

	public static SlotMap getToSlot( ClsMap targetCls ) {
		Collection<SlotMap> slots = targetCls.getSlotMaps();
		Iterator<SlotMap> slotItr = slots.iterator();
		SlotMap slot;
		while (slotItr.hasNext()) {
			slot = slotItr.next();
			if ( slot.getName().startsWith( "TO" ) ) return slot;
		}
		return null;
	}

	protected SlotMap _relationSlot = null;

	protected ClsMap _reifiedCls = null;

	protected Integer _sourceOid = 0;

	protected SeedpodDO _sourceObject = null;

	protected boolean _isOneToOne = false;
	protected boolean _isRequired = false;

	public Relationship(SlotMap slot) {
		_relationSlot = slot;
		_isOneToOne = !slot.isMultiple();
		_isRequired = !slot.isNullable();
		_sourceOid = null;
		_sourceObject = null;
	}

	public Relationship(SlotMap slot, int sourceOid) {
		_relationSlot = slot;
		_sourceOid = sourceOid;
		try {
			_sourceObject = PMFactory.getInstance().createManager().createObject( sourceOid );
		} catch (NoObjectFoundException e) {
			_sourceObject = null;
		} catch (SeedpodException e) {
			_sourceObject = null;
		}

		_isOneToOne = !slot.isMultiple(); // this is the same as isAssociated();
		_isRequired = !slot.isNullable();
	}

	public Relationship(SlotMap slot, SeedpodDO sourceObj) {
		_relationSlot = slot;
		_sourceOid = sourceObj.getOid();
		_isOneToOne = !slot.isMultiple();
		_isRequired = !slot.isNullable();
		_sourceObject = sourceObj;
	}

	public Integer getSourceOid() {
		return _sourceOid;
	}

	public abstract ArrayList<Object> getTargetObjects();

	public boolean isOneToOne() {
		return _isOneToOne;
	}

	public boolean isRequired() {
		return _isRequired;
	}

	public void setIsOneToOne( boolean b ) {
		_isOneToOne = b;
	}

	/**
	 * @param required
	 *            the _isRequired to set
	 */
	public void setIsRequired( boolean required ) {
		_isRequired = required;
	}

	/**
	 * @param cls
	 *            the _reifiedCls to set
	 */
	public void setReifiedCls( ClsMap cls ) {
		_reifiedCls = cls;
	}

	/**
	 * @param object
	 *            the _sourceObject to set
	 */
	public void setSourceObject( SeedpodDO object ) {
		_sourceObject = object;
	}

	public void setSourceOid( Integer oid ) {
		_sourceOid = oid;
	}

}
